home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / unix / c / getcwd < prev    next >
Text File  |  1996-11-09  |  7KB  |  372 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/getcwd,v $
  4.  * $Date: 1996/10/30 21:59:01 $
  5.  * $Revision: 1.3 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: getcwd,v $
  10.  * Revision 1.3  1996/10/30 21:59:01  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.2  1996/05/06 09:01:35  unixlib
  14.  * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
  15.  * Saved for 3.7a release.
  16.  *
  17.  * Revision 1.1  1996/04/19 21:35:27  simon
  18.  * Initial revision
  19.  *
  20.  * Completely re-written by Alun Jones, auj@aber.ac.uk, 23/2/94,
  21.  * The original version corrupted the P.S.D. when run.
  22.  *
  23.  * OS_Args 7 and Prefix$Dir hacke by Simon Callan
  24.  * thanks to Andy (torq@gnu.ai.mit.edu) for the OS calls.
  25.  ***************************************************************************/
  26.  
  27. static const char rcs_id[] = "$Id: getcwd,v 1.3 1996/10/30 21:59:01 unixlib Rel $";
  28.  
  29. #include <errno.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <sys/os.h>
  34. #include <sys/param.h>
  35. #include <sys/syslib.h>
  36. #include <sys/swis.h>
  37.  
  38. char *
  39. getcwd (char *buffer, size_t size)
  40. {
  41.   char ro_path[MAXPATHLEN];
  42.   char var[30];            /* Added by Steffan Corley,
  43.                    is there a known limit on the length of this variable? */
  44.   char *rp = ro_path + MAXPATHLEN - 1;
  45.   char b[MAXPATHLEN];
  46.   register char *s, *t;
  47.   int r[10];
  48.   _kernel_oserror *e;
  49.   int handle;
  50.  
  51.   if (size == 0 && buffer)
  52.     {
  53.       errno = EINVAL;
  54.       return 0;
  55.     }
  56.  
  57.   /* Try to read CSD variable - added by Steffan Corley for !Virtual
  58.      compatibility */
  59.  
  60.   r[0] = (int) "FileSwitch$CurrentFilingSystem";
  61.   r[1] = (int) ro_path;
  62.   r[2] = MAXPATHLEN - 1;
  63.   r[3] = 0;
  64.   r[4] = 0;
  65.   os_swi (OS_ReadVarVal, r);
  66.  
  67.   if (r[2] > 0)
  68.     {
  69.       ro_path[r[2]] = '\0';
  70.       strcpy (var, "FileSwitch$");
  71.       strcat (var, ro_path);
  72.       strcat (var, "$CSD");
  73.       strcat (ro_path, ":");
  74.  
  75.       r[0] = (int) var;
  76.       r[1] = (int) (ro_path + (handle = strlen (ro_path)));
  77.       r[2] = MAXPATHLEN - 1 - handle;
  78.       r[3] = 0;
  79.       r[4] = 0;
  80.       os_swi (OS_ReadVarVal, r);
  81.  
  82.       if (r[2] > 0)
  83.     {            /* Read CSD var worked, parse the path name */
  84.       ro_path[r[2] + handle] = '\0';
  85.       s = ro_path;
  86.       t = buffer;
  87.       *t++ = '/';
  88.       size--;
  89.       while (*s && *s != '$' && size-- > 0)
  90.         *t++ = *s++;
  91.  
  92.       while (*s && size-- > 0)
  93.         {
  94.           if (*s != '.')
  95.         *t++ = *s;
  96.           else
  97.         *t++ = '/';
  98.           s++;
  99.         }
  100.       if (size == 0)
  101.         {
  102.           errno = ERANGE;
  103.           return 0;
  104.         }
  105.       else
  106.         {
  107.           *t = '\0';
  108.           return buffer;
  109.         }
  110.     }
  111.     }
  112.  
  113.   /* Try OS_Args 7 (get cannonicalised name) */
  114.  
  115.   /* Open CSD for read only */
  116.   if (!os_fopen (0x40, "@", &handle))
  117.     {
  118.       r[0] = 7;
  119.       r[1] = handle;
  120.       r[2] = (int) ro_path;
  121.       r[5] = MAXPATHLEN;
  122.       e = os_swi (OS_Args, r);
  123.       os_fclose (handle);
  124.       if (!e)
  125.     {            /* OS_ARGS 7 worked, parse the path name */
  126.       s = ro_path;
  127.       t = buffer;
  128.       *t++ = '/';
  129.       size--;
  130.       while (*s && *s != '$' && size-- > 0)
  131.         *t++ = *s++;
  132.  
  133.       while (*s && size-- > 0)
  134.         {
  135.           if (*s != '.')
  136.         *t++ = *s;
  137.           else
  138.         *t++ = '/';
  139.           s++;
  140.         }
  141.       if (size == 0)
  142.         {
  143.           errno = ERANGE;
  144.           return 0;
  145.         }
  146.       else
  147.         {
  148.           *t = '\0';
  149.           return buffer;
  150.         }
  151.     }
  152.     }
  153.  
  154.   r[0] = (int) "Prefix$Dir";
  155.   r[1] = (int) ro_path;
  156.   r[2] = MAXPATHLEN - 1;
  157.   r[3] = 0;
  158.   r[4] = 0;
  159.   os_swi (OS_ReadVarVal, r);
  160.   if (r[2] > 0)
  161.     {
  162.       ro_path[r[2]] = '\0';
  163.       s = ro_path;
  164.       t = buffer;
  165.       *t++ = '/';
  166.       size--;
  167.       while (*s && *s != '$' && size-- > 0)
  168.     *t++ = *s++;
  169.  
  170.       while (*s && size-- > 0)
  171.     {
  172.       if (*s != '.')
  173.         *t++ = *s;
  174.       else
  175.         *t++ = '/';
  176.       s++;
  177.     }
  178.       if (size == 0)
  179.     {
  180.       errno = ERANGE;
  181.       return 0;
  182.     }
  183.       else
  184.     {
  185.       *t = '\0';
  186.       return buffer;
  187.     }
  188.     }
  189.   /* Search backwards up the tree.
  190.    */
  191.   *rp = 0;
  192.   while (1)
  193.     {
  194.       /* Read current directory name
  195.        */
  196.       r[0] = 6;
  197.       r[2] = (int) b;
  198.       if (e = os_swi (OS_GBPB, r))
  199.     {
  200.       /* Failed to read dirname
  201.        * So swap CSD & PSD then chdir back to original
  202.        * directory.
  203.        */
  204.       __seterr (e);
  205.       if (*rp)
  206.         {
  207.           r[0] = 0;
  208.           r[1] = (int) "\\";
  209.           if (!os_swi (OS_FSControl, r))
  210.         {
  211.           /* cd \ successful, so now need to cd \.{rp}
  212.            */
  213.           *--rp = '.';
  214.           *--rp = '\\';
  215.         }
  216.           r[0] = 0;
  217.           r[1] = (int) rp;
  218.           os_swi (OS_FSControl, r);
  219.         }
  220.       return 0;
  221.     }
  222.  
  223.       /* If at root directory then break
  224.        */
  225.       if ((b[2] == '$') && (b[1] == 1))
  226.     {
  227.       break;
  228.     }
  229.  
  230.       /* Copy the directory name into the RISC OS name
  231.        * buffer.
  232.        */
  233.       rp -= b[1];
  234.       memcpy (rp, b + 2, b[1]);
  235.       *--rp = '.';
  236.  
  237.       /* Now select PSD.
  238.        */
  239.       r[0] = 0;
  240.       r[1] = (int) "\\";
  241.       if (os_swi (OS_FSControl, r))
  242.     {
  243.       /* If cd \ failed then just cd ^
  244.        */
  245.       r[0] = 0;
  246.       r[1] = (int) "^";
  247.       os_swi (OS_FSControl, r);
  248.     }
  249.       else
  250.     {
  251.       /* Select new PSD.^
  252.        * This ensures that the PSD doesn't get corrupted by
  253.        * calling getcwd()
  254.        */
  255.       r[0] = 0;
  256.       r[1] = (int) "\\.^";
  257.       os_swi (OS_FSControl, r);
  258.     }
  259.     }
  260.  
  261.   /* OK, reached the root directory.
  262.    */
  263.   *--rp = '$';
  264.  
  265.   /* Again, PSD then original directory
  266.    */
  267.   r[0] = 0;
  268.   r[1] = (int) "\\";
  269.   if (e = os_swi (OS_FSControl, r))
  270.     {
  271.       __seterr (e);
  272.       return 0;
  273.     }
  274.  
  275.   r[0] = 0;
  276.   r[1] = (int) rp;
  277.   if (e = os_swi (OS_FSControl, r))
  278.     {
  279.       __seterr (e);
  280.       return 0;
  281.     }
  282.  
  283.   /* OK, rp now contains the current directory, and
  284.    * the PSD is unchanged.
  285.    *
  286.    * Next find the FS name.
  287.    */
  288.  
  289.   /* FS number
  290.    */
  291.   if (e = os_args (0, 0, 0, r))
  292.     {
  293.       __seterr (e);
  294.       return 0;
  295.     }
  296.  
  297.   /* Convert number to name
  298.    */
  299.   r[1] = r[0];
  300.   r[2] = (int) b + 1;
  301.   r[3] = MAXPATHLEN;
  302.   r[0] = 33;
  303.   if (e = os_swi (OS_FSControl, r))
  304.     {
  305.       __seterr (e);
  306.       return (0);
  307.     }
  308.  
  309.   /* Now have "/ADFS::", for example in b.
  310.    */
  311.   b[0] = '/';
  312.   strcat (b, "::");
  313.  
  314.   /* Copy the disk name across to v
  315.    */
  316.   if (strlen (b) < size)
  317.     {
  318.       strcpy (buffer, b);
  319.     }
  320.   else
  321.     {
  322.       errno = ERANGE;
  323.       return 0;
  324.     }
  325.  
  326.   /* Next find the disk name
  327.    */
  328.   r[0] = 5;
  329.   r[2] = (int) b;
  330.   if (e = os_swi (OS_GBPB, r))
  331.     {
  332.       __seterr (e);
  333.       return 0;
  334.     }
  335.   *(b + b[0] + 1) = '\0';
  336.   strcat (b, ".$");
  337.   if (strlen (buffer) + strlen (b + 1) < size)
  338.     {
  339.       strcat (buffer, b + 1);
  340.     }
  341.   else
  342.     {
  343.       errno = ERANGE;
  344.       return 0;
  345.     }
  346.  
  347.   /* buffer now contains "/ADFS::fred.$", for example.
  348.  
  349.    * Finally convert the RISC OS name from rp, appending it to v.
  350.    */
  351.   s = buffer + strlen (buffer);
  352.   for (t = rp + 1; *t; t++)
  353.     {
  354.       if (s - buffer == size)
  355.     {
  356.       errno = ERANGE;
  357.       return 0;
  358.     }
  359.       *s++ = (*t == '.') ? '/' : *t;
  360.     }
  361.   *s = '\0';
  362.   return buffer;
  363. }
  364.  
  365. /* BSD version of getcwd.  */
  366.  
  367. char *
  368. getwd (char *buffer)
  369. {
  370.   return getcwd (buffer, 256);
  371. }
  372.